"""
Bch Client class
@author : U{ zhangxinlei01<zhangxinlei01@baidu.com>}
@copyright : baidu.com
@date : 2015-11-27
@version : 1.0.0.0
"""
import cStringIO
import copy
import httplib
import os
import json
import logging
import shutil

import baidubce
from baidubce import bce_client_configuration
from baidubce import utils
from baidubce.auth import bce_v1_signer
from baidubce.bce_base_client import BceBaseClient
from baidubce.exception import BceClientError
from baidubce.exception import BceServerError
from baidubce.exception import BceHttpClientError
from baidubce.http import bce_http_client
from baidubce.http import handler
from baidubce.http import http_content_types
from baidubce.http import http_headers
from baidubce.http import http_methods
from baidubce.services import bch
from baidubce.utils import required
from sqlite3.dbapi2 import paramstyle

_logger = logging.getLogger(__name__)
class BchClient(BceBaseClient):
    """
        BchClient
    """
    def __init__(self, config=None):
        BceBaseClient.__init__(self, config)
    
    def reset_ftp_pwd(self, account, password, config=None):
        """
            BchClient
        """
        params = {}
        params['resetftppwd'] = ''
        path = 'v1/host/' + account
        headers = {}
        headers[http_headers.CONTENT_TYPE] = http_content_types.JSON
        return self._send_request(
            http_methods.PUT, 
            path,
            body=json.dumps({'password':password}),
            headers=headers,
            params=params,
            config=config)
        
    def create_host(self, account, hostName, packageId, 
                    purchaseLength, ftpPassword, domains,
                    recordName, hostContact, accountPassword, config=None):
        """
            BchClient
        """
        params = {}
        params['clientToken'] = 'asdsafasgegewqg2g2egwe111111111'
        path = 'v1/host'
        headers = {}
        headers[http_headers.CONTENT_TYPE] = http_content_types.JSON
        body = {}
        body['account'] = account
        body['hostName'] = hostName
        body['packageId'] = packageId
        body['purchaseLength'] = purchaseLength
        body['ftpPassword'] = ftpPassword
        body['domains'] = domains
        body['recordName'] = recordName
        body['hostContact'] = hostContact
        body['accountPassword'] = accountPassword
        
        return self._send_request(
            http_methods.POST, 
            path,
            body=json.dumps(body),
            headers=headers,
            params=params,
            config=config)
    
    def bind_domains(self, account, domainList, config=None):
        """
            BchClient
        """
        params={}
        params['binddomains'] = ''
        path = 'v1/host/' + account
        headers = {}
        headers[http_headers.CONTENT_TYPE] = http_content_types.JSON
        return self._send_request(
            http_methods.PUT, 
            path,
            body=json.dumps({'domains':domainList}),
            headers=headers,
            params=params,
            config=config)
       
    def get_host_info(self, account, config=None):
        """
            BchClient
        """
        path = 'v1/host/' + account
        headers = {}
        headers[http_headers.CONTENT_TYPE] = http_content_types.JSON
        return self._send_request(
            http_methods.GET, 
            path,
            headers=headers,
            config=config,
            body_parser=BchClient._parse_bch_resp)
       
    def reset_account_pwd(self, account, password, config=None):
        """
            BchClient
        """
        path = 'v1/host/' + account
        params = {}
        params['resetaccountpwd'] = ''
        headers = {}
        headers[http_headers.CONTENT_TYPE] = http_content_types.JSON
        return self._send_request(
            http_methods.PUT, 
            path,
            body=json.dumps({'password':password}),
            headers=headers,
            params=params,
            config=config)
       
    def renew_host(self, account, renew_length, config=None):
        """
            BchClient
        """
        path = 'v1/host/' + account
        params = {}
        params['renewhost'] = ''
        headers = {}
        headers[http_headers.CONTENT_TYPE] = http_content_types.JSON
        return self._send_request(
            http_methods.PUT, 
            path,
            body=json.dumps({'renewLength':renew_length}),
            headers=headers,
            params=params,
            config=config)

    def add_task(self, type, info, config=None):
        """
	    internal api
        """
        path = 'internal/task/add_task'
        params = {}
        headers = {}
        headers[http_headers.CONTENT_TYPE] = http_content_types.JSON
        return self._send_request(
	    http_methods.POST,
	    path,
	    body=json.dumps({'type':type, 'info':info}),
	    headers=headers,
	    params=params,
	    config=config)

    def add_delay_task(self, type, info, delay, config=None):
        """
	    internal api
        """
        path = 'internal/task/add_delay_task'
        params = {}
        headers = {}
        headers[http_headers.CONTENT_TYPE] = http_content_types.JSON
        return self._send_request(
            http_methods.POST,
            path,
            body=json.dumps({'type':type, 'info':info, 'delay':delay}),
            headers=headers,
            params=params,
            config=config)

    @staticmethod
    def _parse_bch_resp(http_response, response):
        """Sets response.body to http_response and response.user_metadata to a dict consists of all http
        headers starts with 'x-bce-meta-'.

        :param http_response: the http_response object returned by HTTPConnection.getresponse()
        :type http_response: httplib.HTTPResponse

        :param response: general response object which will be returned to the caller
        :type response: baidubce.BceResponse

        :return: always true
        :rtype bool
        """
        body = http_response.read()
        if body:
            response.__dict__.update(
                    json.loads(body, object_hook=utils.dict_to_python_object).__dict__)
        response.__setattr__("http_status", http_response.status)
        response.__setattr__("http_reason", http_response.reason)
        response.__setattr__("http_headers", http_response.getheaders())
        http_response.close()
        return True

    @staticmethod
    def _parse_bch_error(http_response, response):
        """Sets response.body to http_response and response.user_metadata to a dict consists of all http
        headers starts with 'x-bce-meta-'.

        :param http_response: the http_response object returned by HTTPConnection.getresponse()
        :type http_response: httplib.HTTPResponse

        :param response: general response object which will be returned to the caller
        :type response: baidubce.BceResponse

        :return: always true
        :rtype bool
        """
        if http_response.status / 100 == httplib.OK / 100:
            return False
        if http_response.status / 100 == httplib.CONTINUE / 100:
            raise BceClientError('Can not handle 1xx http status code')
        bse = None
        body = http_response.read()
        if body:
            d = json.loads(body)
            bse = BceServerError(d['message'], code=d['code'], request_id=d['requestId'])
        if bse is None:
            bse = BceServerError(http_response.reason, request_id=response.metadata.bce_request_id)
        bse.status_code = http_response.status
        raise bse
 
    @staticmethod
    def _merge_config(self, config):
        if config is None:
            return self.config
        else:
            new_config = copy.copy(self.config)
            new_config.merge_non_none_values(config)
            return new_config
        
    def _send_request(
           self, http_method, path,
           body=None, headers=None, params=None,
           config=None,
           body_parser=None):
        config = self._merge_config(self, config)
        if body_parser is None:
            body_parser = handler.parse_json
    
        return bce_http_client.send_request(
            #config, bce_v1_signer.sign, [handler.parse_error, body_parser],
            config, bce_v1_signer.sign, [body_parser],
            http_method, bch.URL_PREFIX + path, body, headers, params)
